/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package systole.view.workers;

import java.awt.Dimension;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.swing.SwingWorker;
import org.jfree.chart.ChartPanel;
import systole.domain.analysis.Analysis;
import systole.domain.signals.Segment;
import systole.domain.signals.SelectedSegment;
import systole.domain.signals.Signal;
import systole.ioHandling.logs.SystoleLogger;
import systole.processor.Slicer;
import systole.processor.filters.FilterProcessor;
import systole.processor.filters.FilterSettings;
import systole.view.charts.XYChart;
import systole.view.imageFlow.ImageFlow;
import systole.view.imageFlow.ImageFlowItem;
import systole.view.tabs.controllers.AnalysisController;
import systole.view.tabs.controllers.SelectionItem;

/**
 *
 * @author jmj
 */
public class WorkerOpenAnalysis extends SwingWorker<Void, Void> {

    private AnalysisController analysisController;
    private Analysis currentAnalysis;
    //filtro
    private XYChart filteredSignalModel;
    private ChartPanel rawSignalChart;
    private ChartPanel filteredSignalChart;
    private Segment segment;
    // slice
    private Signal allSegments;
    private ImageFlow imageFlow;
    private List<ImageFlowItem> items;
    private List<Image> images;
    private Vector<SelectionItem> selectionItems;
    //proceso
    private XYChart allCharts;
    private XYChart derivates;
    private XYChart finalSegment;
    //report
    private ChartPanel reportPanel;
    private boolean sliced = false;
    private boolean processed = false;
    private boolean reported = false;
    private BufferedImage image;

    /**
     * @param analysisController
     */
    public WorkerOpenAnalysis(AnalysisController analysisController) {
        super();
        this.analysisController = analysisController;
        this.currentAnalysis = this.analysisController.getAnalysis();
    }

    private void filter() {
        FilterSettings filtSet = new FilterSettings();
        filtSet.createDefault(this.currentAnalysis.getSignalFrequency().getFrequency().doubleValue());

        // primer grafico -> señal cruda
        XYChart rawSignal = new XYChart("Señal Original", "Muestras", "Amplitud (%)");
        rawSignal.setShowLegend(false);
        rawSignal.addSeries("Tren de Pulsos", this.currentAnalysis.getRawSignal().getSegment().toDoubleArray(), 1);
        this.rawSignalChart = rawSignal.plot();
        // onda filtrada
        this.segment = FilterProcessor.filterPulseWave(this.currentAnalysis.getRawSignal().getSegment(), filtSet);

        if (this.currentAnalysis.getRawSignal().isInverted()) {
            this.segment = this.segment.invert();
        }

        // segundo grafico -> señal invertida y filtrada
        this.filteredSignalModel = new XYChart("Señal Filtrada", "Muestras", "Amplitud (%)");
        this.filteredSignalModel.addSeries("Tren de Pulsos", this.segment.toDoubleArray(), 1);
        this.filteredSignalModel.setShowLegend(false);
        this.filteredSignalChart = this.filteredSignalModel.plot();

    }

    private void slice() {
        Slicer slicer = new Slicer();
        this.allSegments = slicer.sliceSignal(segment);
        Vector<Segment> slicedSegments = this.allSegments.getSegments();
        if ((slicedSegments != null) && (!slicedSegments.isEmpty())) {
            this.items = new Vector<ImageFlowItem>();
            this.images = new Vector<Image>();
            ImageFlowItem flowItem;
            XYChart thumb;
            this.selectionItems = new Vector<SelectionItem>();
            for (int i = 0; i < slicedSegments.size(); i++) {
                thumb = new XYChart("Segmento " + (i + 1));
                thumb.setShowLegend(false);
                thumb.addSeries("", slicedSegments.elementAt(i).toDoubleArray(), 1);
                flowItem = new ImageFlowItem(thumb.plotThumbnail(225, 225, false), "Segmento " + (i + 1));
                this.items.add(flowItem);
                thumb.setShowTitle(false);
                this.images.add(thumb.plotThumbnail(200, 150, false));
                this.selectionItems.add(new SelectionItem(i));
            }
            this.sliced = true;
        }
    }

    private void calculate() {
        if ((this.currentAnalysis.getSelectedSegments() != null) && (this.currentAnalysis.getFinalSegment() != null)) {

            this.allCharts = new XYChart("Segmentos", "Muestras", "Amplitud (%)");

            Iterator<SelectedSegment> segments = this.currentAnalysis.getSelectedSegments().iterator();
            while (segments.hasNext()) {
                SelectedSegment selectedSegment = segments.next();
                this.allCharts.addSeries("Seg-" + (selectedSegment.getNumber() + 1), selectedSegment.getSegment().toDoubleArray(), 1);
                SelectionItem selectItem = this.selectionItems.get(selectedSegment.getNumber());
                if (selectItem != null) {
                    selectItem.setSelected(true);
                }
            }

            double frequency = this.currentAnalysis.getSignalFrequency().getFrequency().doubleValue();
            this.finalSegment = new XYChart("Curva Final", "Tiempo (ms)", "Amplitud (%)");
            this.finalSegment.addSeries("Latido", this.currentAnalysis.getFinalSegment().getFinalSegment().toDoubleArray(), frequency);

            this.derivates = new XYChart("Derivadas", "Tiempo (ms)", "Amplitud (%)");
            this.derivates.addSeries("Latido", this.currentAnalysis.getFinalSegment().getFinalSegment().toDoubleArray(), frequency);
            this.derivates.addSeries("Derivada 1ra", this.currentAnalysis.getFinalSegment().getFirstDerivatite().toDoubleArray(), frequency);
            this.derivates.addSeries("Derivada 2da", this.currentAnalysis.getFinalSegment().getSecondDerivative().toDoubleArray(), frequency);
            this.derivates.addSeries("Derivada 3ra", this.currentAnalysis.getFinalSegment().getThirdDerivative().toDoubleArray(), frequency);
            this.derivates.addSeries("Derivada 4ta", this.currentAnalysis.getFinalSegment().getFourthDerivative().toDoubleArray(), frequency);

            this.processed = true;
        }
    }

    private void report() {
        if ((this.currentAnalysis != null) && (this.currentAnalysis.getFinalSegment() != null)) {

            XYChart chart = new XYChart("Registro de Variación", "[ms]", "[%]");

            chart.addSeries("", this.currentAnalysis.getFinalSegment().getFinalSegment().toDoubleArray(), this.currentAnalysis.getSignalFrequency().getFrequency().doubleValue());
            chart.setShowLegend(false);
            chart.setShowTitle(false);

            this.reportPanel = chart.blackAndWhitePlot();
            this.reportPanel.setMaximumSize(new Dimension(400, 230));
            this.image = chart.plotThumbnail(280, 200, true);
            this.reportPanel.setMouseZoomable(false);
            this.reportPanel.setPopupMenu(null);
            this.reported = true;
        }
    }

    private void loadAnalysis() {
        this.analysisController.getAnalysis().setAllSegments(this.allSegments);
        this.analysisController.getAnalysis().setSignalFiltered(this.segment);
        this.analysisController.getFrmAnalysis().addFilteredCharts(this.rawSignalChart, this.filteredSignalChart, this.filteredSignalModel);

        if (this.sliced) {
            this.imageFlow = new ImageFlow(this.items, this.analysisController.getFrmAnalysis().getJpnlSegments().getImagesFlow());
            this.analysisController.getFrmAnalysis().getJpnlSegments().getImagesFlow().addFlowCharts(this.imageFlow);
            this.analysisController.getFrmAnalysis().getJpnlSegments().getImageMap().loadImageList(this.images);
            this.analysisController.getFrmAnalysis().getAccordionSegments().updatePanel();
            this.analysisController.getSelectionModel().loadConfirmedSegments(this.analysisController.getAnalysis(), this.selectionItems);
        }

        if (this.processed) {
            this.analysisController.getResultsModel().loadAnalysisResultCalculated(null, null);
            this.analysisController.getFrmAnalysis().addProcessedCharts(this.allCharts, this.finalSegment, this.derivates);
        }

        if (this.reported) {
            this.analysisController.getFrmAnalysis().getJReportView().getPnlReport().loadNewChart(this.reportPanel);
            this.analysisController.getFrmAnalysis().getJReportView().showReport();
            this.analysisController.getReportModel().updatePlotImage(this.image);
        }
    }

    @Override
    protected Void doInBackground() throws Exception {
        try {
            this.filter();
            this.slice();
            this.calculate();
            this.report();
        } catch (Exception e) {
            SystoleLogger.getInstance().logError(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void done() {
        this.loadAnalysis();
    }
}
